/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.plechinger.mcremote.client;

import com.plechinger.mcremote.client.dialog.LogDialog;
import com.plechinger.mcremote.client.dialog.PlayerListDialog;
import com.plechinger.mcremote.data.*;
import com.plechinger.mcremote.server.craft.CraftLogElement;
import java.awt.BorderLayout;
import java.awt.Cursor;
import java.awt.GridLayout;
import java.io.IOException;
import java.net.UnknownHostException;
import java.security.InvalidKeyException;
import java.util.List;
import java.util.ResourceBundle;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;
import static javax.swing.JOptionPane.*;

/**
 *
 * @author Lukas
 */
public class ClientGUI extends javax.swing.JFrame {

    private static final ResourceBundle messages = Client.getClient().getResourceBundle();
    private Connector connector;
    private String pass;

    /**
     * Creates new form ClientGUI
     */
    public ClientGUI() {
        initComponents();
        setTitle(messages.getString("clientGUI.title"));
        authDialog();
        updateStatus();
    }

    private void authDialog() {

        JPanel panel = new JPanel();
        panel.setLayout(new GridLayout(4, 1));
        JLabel username = new JLabel("Host(:port)");
        JLabel password = new JLabel("Passwort");


        JTextField textField = new JTextField(12);
        textField.setText(ClientSettings.getSettings().getHost());
        JPasswordField passwordField = new JPasswordField(12);
        passwordField.setText(ClientSettings.getSettings().getPassword());
        panel.add(username);
        panel.add(textField);
        panel.add(password);
        panel.add(passwordField);
        JFrame frame = new JFrame("Host/Passwort");
        int a = JOptionPane.showConfirmDialog(this, panel, "Host und Passwort eingeben", JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE);
        //Operation that will do when user click 'OK'  
        if (a == JOptionPane.OK_OPTION) {
            try {
                String hostPort = textField.getText();
                pass = new String(passwordField.getPassword());
                String[] parts = hostPort.split(":", 2);
                String host;
                int port;
                if (parts.length == 2) {
                    host = parts[0];
                    port = Integer.parseInt(parts[1]);
                } else {
                    host = hostPort;
                    port = 29900;
                }

                connector = new Connector(host, port);

                ClientSettings.getSettings().setPassword(pass);
                ClientSettings.getSettings().setHost(hostPort);
                ClientSettings.getSettings().store();
            } //Operation that will do when user click 'Cancel'
            catch (UnknownHostException ex) {
                Logger.getLogger(ClientGUI.class.getName()).log(Level.SEVERE, null, ex);
            }

        } else if (a == JOptionPane.CANCEL_OPTION) {
            JOptionPane.showMessageDialog(frame, "You pressed Cancel button");
        }
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;

        panSpacer = new javax.swing.JPanel();
        jPanel2 = new javax.swing.JPanel();
        jButton3 = new javax.swing.JButton();
        panelActions = new javax.swing.JPanel();
        btStartServer = new javax.swing.JButton();
        btServerStop = new javax.swing.JButton();
        btServerListPlayers = new javax.swing.JButton();
        jLabel1 = new javax.swing.JLabel();
        jLabel2 = new javax.swing.JLabel();
        jLabel3 = new javax.swing.JLabel();
        lblStatusStatus = new javax.swing.JLabel();
        lblStatusOnline = new javax.swing.JLabel();
        lblStatusErrorsWarnings = new javax.swing.JLabel();
        jLabel7 = new javax.swing.JLabel();
        lblStatusRuntime = new javax.swing.JLabel();
        btStatusUpdate = new javax.swing.JButton();
        btServerLog = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setMinimumSize(new java.awt.Dimension(560, 280));
        setPreferredSize(new java.awt.Dimension(520, 280));

        panSpacer.setBorder(javax.swing.BorderFactory.createEmptyBorder(5, 5, 5, 5));
        panSpacer.setLayout(new java.awt.BorderLayout());

        jButton3.setText(messages.getString("client.close")); // NOI18N
        jButton3.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                onClose(evt);
            }
        });
        jPanel2.add(jButton3);

        panSpacer.add(jPanel2, java.awt.BorderLayout.PAGE_END);

        panelActions.setLayout(new java.awt.GridBagLayout());

        btStartServer.setText(messages.getString("client.serverStart")); // NOI18N
        btStartServer.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                onStartServer(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 3;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
        panelActions.add(btStartServer, gridBagConstraints);

        btServerStop.setText(messages.getString("client.serverStop")); // NOI18N
        btServerStop.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                onStopServer(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 4;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
        panelActions.add(btServerStop, gridBagConstraints);

        btServerListPlayers.setText("Aktuelle Spieler");
        btServerListPlayers.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                onServerListPlayers(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 3;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
        panelActions.add(btServerListPlayers, gridBagConstraints);

        jLabel1.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N
        jLabel1.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        jLabel1.setText("Status");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.ipadx = 3;
        gridBagConstraints.ipady = 3;
        gridBagConstraints.insets = new java.awt.Insets(8, 8, 8, 8);
        panelActions.add(jLabel1, gridBagConstraints);

        jLabel2.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N
        jLabel2.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        jLabel2.setText("Spieler online");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.ipadx = 3;
        gridBagConstraints.ipady = 3;
        gridBagConstraints.insets = new java.awt.Insets(8, 8, 8, 8);
        panelActions.add(jLabel2, gridBagConstraints);

        jLabel3.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N
        jLabel3.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        jLabel3.setText("Fehler/Warnungen");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.ipadx = 3;
        gridBagConstraints.ipady = 3;
        gridBagConstraints.insets = new java.awt.Insets(8, 8, 8, 8);
        panelActions.add(jLabel3, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.ipadx = 50;
        gridBagConstraints.ipady = 3;
        gridBagConstraints.insets = new java.awt.Insets(8, 8, 8, 8);
        panelActions.add(lblStatusStatus, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.ipadx = 50;
        gridBagConstraints.ipady = 3;
        gridBagConstraints.insets = new java.awt.Insets(8, 8, 8, 8);
        panelActions.add(lblStatusOnline, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.ipadx = 50;
        gridBagConstraints.ipady = 3;
        gridBagConstraints.insets = new java.awt.Insets(8, 8, 8, 8);
        panelActions.add(lblStatusErrorsWarnings, gridBagConstraints);

        jLabel7.setFont(new java.awt.Font("Tahoma", 1, 11)); // NOI18N
        jLabel7.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        jLabel7.setText("Läuft seit");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 4;
        gridBagConstraints.gridwidth = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.ipadx = 3;
        gridBagConstraints.ipady = 3;
        gridBagConstraints.insets = new java.awt.Insets(8, 8, 8, 8);
        panelActions.add(jLabel7, gridBagConstraints);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 4;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.ipadx = 50;
        gridBagConstraints.ipady = 3;
        gridBagConstraints.insets = new java.awt.Insets(8, 8, 8, 8);
        panelActions.add(lblStatusRuntime, gridBagConstraints);

        btStatusUpdate.setText("Status aktualisieren");
        btStatusUpdate.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                onServerUpdate(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 3;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
        panelActions.add(btStatusUpdate, gridBagConstraints);

        btServerLog.setText("Log anzeigen");
        btServerLog.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                onShowLog(evt);
            }
        });
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 4;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.insets = new java.awt.Insets(3, 3, 3, 3);
        panelActions.add(btServerLog, gridBagConstraints);

        panSpacer.add(panelActions, java.awt.BorderLayout.CENTER);

        getContentPane().add(panSpacer, java.awt.BorderLayout.CENTER);

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void onStartServer(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_onStartServer
        Response res = doRequest(RequestMethod.START);
        if (res.getStatus() == ResponseStatus.OK) {
            showMessageDialog(this, "Server erfolgreich gestartet!", "Info", INFORMATION_MESSAGE);
            updateStatus();
        } else {
            
            System.out.println(res.getResponseObject());
            showError(res.getMessage(), (Exception) res.getResponseObject());
        }

    }//GEN-LAST:event_onStartServer

    private void onClose(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_onClose
        System.exit(0);
    }//GEN-LAST:event_onClose

    private void onStopServer(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_onStopServer
        Response res = doRequest(RequestMethod.STOP);
        if (res.getStatus() == ResponseStatus.OK) {
            showMessageDialog(this, "Server erfolgreich gestoppt!", "Info", INFORMATION_MESSAGE);
            updateStatus();
        } else {
            showError(res.getMessage(), (Exception) res.getResponseObject());
        }

    }//GEN-LAST:event_onStopServer

    private void onServerListPlayers(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_onServerListPlayers
        Response res = doRequest(RequestMethod.LIST);
        if (res.getStatus() == ResponseStatus.OK) {
            List players = (List) res.getResponseObject();
            if (players.size() > 0) {
                PlayerListDialog dialog = new PlayerListDialog(this, true);
                dialog.setList(players);
                dialog.setVisible(true);
            } else {
                showMessageDialog(this, "Keine Spieler online", "Info", INFORMATION_MESSAGE);
            }

        } else {
            showError(res.getMessage(), (Exception) res.getResponseObject());
        }
    }//GEN-LAST:event_onServerListPlayers

    private void onServerUpdate(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_onServerUpdate
        updateStatus();
    }//GEN-LAST:event_onServerUpdate

    private void onShowLog(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_onShowLog
        Response res = doRequest(RequestMethod.LOG);
        if (res.getStatus() == ResponseStatus.OK) {
            List<CraftLogElement> log = (List<CraftLogElement>) res.getResponseObject();
            LogDialog dialog = new LogDialog(this, true);
            dialog.setLog(log);
            dialog.setVisible(true);

        } else {
            showError(res.getMessage(), (Exception) res.getResponseObject());
        }
    }//GEN-LAST:event_onShowLog

    private void updateStatus() {
        //final JFrame frame = this;
        lblStatusStatus.setText("update...");
        lblStatusErrorsWarnings.setText("");
        lblStatusOnline.setText("");
        lblStatusRuntime.setText("");
        Thread updater = new Thread(new Runnable() {

            public void run() {
                /*
                 * WaitPanel wp=new WaitPanel(); frame.remove(panSpacer);
                 * frame.add(wp, BorderLayout.CENTER);
                frame.repaint();
                 */


                try {
                    Request req = new Request();
                    req.setPassword(pass);
                    req.setMethod(RequestMethod.STATUS);
                    Response response = connector.send(req);
                    if (response.getStatus() == ResponseStatus.OK) {
                        Status status = (Status) response.getResponseObject();
                        lblStatusStatus.setText((status.isServerOn()) ? "online" : "offline");
                        lblStatusErrorsWarnings.setText(status.getCountErrors() + "/" + status.getCountWarnings());
                        lblStatusOnline.setText(status.getCountPlayers() + "");
                        lblStatusRuntime.setText(String.format("%dd %dh %dm %ds",
                                TimeUnit.MILLISECONDS.toDays(status.getTime()),
                                TimeUnit.MILLISECONDS.toHours(status.getTime()) - TimeUnit.DAYS.toHours(TimeUnit.MILLISECONDS.toDays(status.getTime())),
                                TimeUnit.MILLISECONDS.toMinutes(status.getTime()) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(status.getTime())),
                                TimeUnit.MILLISECONDS.toSeconds(status.getTime())
                                - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(status.getTime()))));
                    } else {
                        lblStatusStatus.setText("fehler");
                    }

                } catch (IOException ex) {
                    lblStatusStatus.setText("nicht erreichbar");


                } catch (InvalidKeyException ex) {
                    lblStatusStatus.setText("ungültige verschlüsselung");


                } catch (ClassNotFoundException ex) {
                    Logger.getLogger(ClientGUI.class.getName()).log(Level.SEVERE, null, ex);
                }
                /*
                 * frame.remove(wp); frame.add(panSpacer, BorderLayout.CENTER);
                 * wp=null;
                frame.repaint();
                 */
            }
        });

        updater.start();

    }

    private Response doRequest(RequestMethod method) {
        try {
            Request req = new Request();
            req.setPassword(pass);
            req.setMethod(method);

            Response res = connector.send(req);

            return res;


        } catch (IOException ex) {
            Logger.getLogger(ClientGUI.class.getName()).log(Level.SEVERE, null, ex);
            showError(
                    "Fehler", ex);
        } catch (InvalidKeyException ex) {
            Logger.getLogger(ClientGUI.class.getName()).log(Level.SEVERE, null, ex);
            showError(
                    "Fehler", ex);
        } catch (ClassNotFoundException ex) {
            showError("Fehler", ex);
        }
        return null;
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btServerListPlayers;
    private javax.swing.JButton btServerLog;
    private javax.swing.JButton btServerStop;
    private javax.swing.JButton btStartServer;
    private javax.swing.JButton btStatusUpdate;
    private javax.swing.JButton jButton3;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel7;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JLabel lblStatusErrorsWarnings;
    private javax.swing.JLabel lblStatusOnline;
    private javax.swing.JLabel lblStatusRuntime;
    private javax.swing.JLabel lblStatusStatus;
    private javax.swing.JPanel panSpacer;
    private javax.swing.JPanel panelActions;
    // End of variables declaration//GEN-END:variables

    private void showError(String message, Exception throwable) {
        showMessageDialog(this, message + "\n" + throwable.getMessage(), "Fehler", ERROR_MESSAGE);
    }
}
